package com.example.stuwork.service.impl;

import com.example.stuwork.common.Result;
import com.example.stuwork.dao.AssignmentDao;
import com.example.stuwork.dao.AssignmentAllocationDao;
import com.example.stuwork.dao.SubmissionDao;
import com.example.stuwork.pojo.Assignment;
import com.example.stuwork.pojo.AssignmentAllocation;
import com.example.stuwork.pojo.Submission;
import com.example.stuwork.service.OSSService;
import com.example.stuwork.service.SubmissionService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 作业提交服务实现类
 */
@Service
public class SubmissionServiceImpl implements SubmissionService {
    
    private static final Logger logger = LoggerFactory.getLogger(SubmissionServiceImpl.class);
    
    @Autowired
    private SubmissionDao submissionDao;
    
    @Autowired
    private AssignmentDao assignmentDao;
    
    @Autowired
    private AssignmentAllocationDao assignmentAllocationDao;
    
    @Autowired
    private OSSService ossService;

    @Override
    public Result<List<Submission>> getAllSubmissions() {
        try {
            List<Submission> submissions = submissionDao.findAll();
            return Result.success(submissions);
        } catch (Exception e) {
            logger.error("获取所有提交记录失败", e);
            return Result.error("获取提交记录失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Submission> getSubmissionById(Long submissionId) {
        try {
            Submission submission = submissionDao.getById(submissionId);
            if (submission == null) {
                return Result.error("提交记录不存在");
            }
            return Result.success(submission);
        } catch (Exception e) {
            logger.error("获取提交记录详情失败，提交ID: " + submissionId, e);
            return Result.error("获取提交记录详情失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Submission>> getSubmissionsByAssignmentId(Long assignmentId) {
        try {
            List<Submission> submissions = submissionDao.findByAssignmentId(assignmentId);
            return Result.success(submissions);
        } catch (Exception e) {
            logger.error("获取作业提交记录列表失败，作业ID: " + assignmentId, e);
            return Result.error("获取作业提交记录列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Submission>> getSubmissionsByStudentId(String studentId) {
        try {
            List<Submission> submissions = submissionDao.findByStudentId(studentId);
            return Result.success(submissions);
        } catch (Exception e) {
            logger.error("获取学生提交记录列表失败，学生ID: " + studentId, e);
            return Result.error("获取学生提交记录列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Submission> getSubmissionByAssignmentIdAndStudentId(Long assignmentId, String studentId) {
        try {
            Submission submission = submissionDao.findByAssignmentIdAndStudentId(assignmentId, studentId);
            if (submission == null) {
                return Result.error("提交记录不存在");
            }
            return Result.success(submission);
        } catch (Exception e) {
            logger.error("获取提交记录详情失败，作业ID: " + assignmentId + ", 学生ID: " + studentId, e);
            return Result.error("获取提交记录详情失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Submission>> getSubmissionsByAssignmentIdAndStatus(Long assignmentId, Integer status) {
        try {
            List<Submission> submissions = submissionDao.findByAssignmentIdAndStatus(assignmentId, status);
            return Result.success(submissions);
        } catch (Exception e) {
            logger.error("获取作业提交记录列表失败，作业ID: " + assignmentId + ", 状态: " + status, e);
            return Result.error("获取作业提交记录列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Submission>> getSubmissionsForGradingByTeacherId(String teacherId) {
        try {
            List<Submission> submissions = submissionDao.findSubmissionsForGradingByTeacherId(teacherId);
            return Result.success(submissions);
        } catch (Exception e) {
            logger.error("获取待批改提交记录列表失败，教师ID: " + teacherId, e);
            return Result.error("获取待批改提交记录列表失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Submission> addSubmission(Submission submission, MultipartFile file) {
        try {
            // 检查作业是否存在
            Assignment assignment = assignmentDao.getById(submission.getAssignmentId());
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            // 检查作业分配记录是否存在
            AssignmentAllocation allocation = assignmentAllocationDao.findByAssignmentIdAndStudentId(
                    submission.getAssignmentId(), submission.getStudentId());
            if (allocation == null) {
                return Result.error("未找到作业分配记录");
            }
            
            // 设置版本号
            Integer version = 1;
            Submission latestSubmission = submissionDao.findLatestVersion(
                    submission.getAssignmentId(), submission.getStudentId());
            if (latestSubmission != null) {
                version = latestSubmission.getVersion() + 1;
            }
            submission.setVersion(version);
            
            // 设置提交时间
            Date now = new Date();
            submission.setSubmitTime(now);
            
            // 检查是否超过截止时间
            if (now.after(assignment.getDeadline())) {
                submission.setIsLate(1); // 已超时
            } else {
                submission.setIsLate(0); // 未超时
            }
            
            // 设置状态为未批改
            submission.setStatus(0);
            
            // 上传文件到OSS
            if (file != null && !file.isEmpty()) {
                String fileUrl = ossService.uploadFile(file);
                submission.setFileUrl(fileUrl);
            }
            
            // 添加提交记录
            submissionDao.insert(submission);
            logger.info("提交记录添加成功，ID: {}", submission.getSubmissionId());
            
            // 更新作业分配记录状态
            allocation.setSubmissionId(submission.getSubmissionId());
            allocation.setStatus(1); // 设置为已提交状态
            int updated = assignmentAllocationDao.update(allocation);
            logger.info("更新作业分配状态结果: 更新行数={}, 状态设置为1(已提交)", updated);
            
            // 额外记录日志以便排查
            AssignmentAllocation updatedAllocation = assignmentAllocationDao.findByAssignmentIdAndStudentId(
                    submission.getAssignmentId(), submission.getStudentId());
            if (updatedAllocation != null) {
                logger.info("更新后的分配记录: ID={}, 状态={}, 提交ID={}", 
                           updatedAllocation.getAllocationId(), 
                           updatedAllocation.getStatus(),
                           updatedAllocation.getSubmissionId());
            } else {
                logger.warn("无法获取更新后的分配记录");
            }
            
            return Result.success(submission);
        } catch (Exception e) {
            logger.error("添加提交记录失败", e);
            return Result.error("添加提交记录失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Submission> updateSubmission(Submission submission) {
        try {
            Submission existingSubmission = submissionDao.getById(submission.getSubmissionId());
            if (existingSubmission == null) {
                return Result.error("提交记录不存在");
            }
            
            submissionDao.update(submission);
            return Result.success(submission);
        } catch (Exception e) {
            logger.error("更新提交记录失败，提交ID: " + submission.getSubmissionId(), e);
            return Result.error("更新提交记录失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Submission> gradeSubmission(Long submissionId, Integer score, String feedback, String teacherId) {
        try {
            Submission submission = submissionDao.getById(submissionId);
            if (submission == null) {
                return Result.error("提交记录不存在");
            }
            
            // 更新提交记录评分信息
            Date now = new Date();
            int result1 = submissionDao.updateGrading(submissionId, score, feedback, teacherId, 1);
            
            // 获取作业分配记录
            AssignmentAllocation allocation = assignmentAllocationDao.findByAssignmentIdAndStudentId(
                    submission.getAssignmentId(), submission.getStudentId());
            
            // 更新作业分配记录状态和分数
            int result2 = 0;
            if (allocation != null) {
                allocation.setScore(score);
                allocation.setStatus(2); // 已批改
                result2 = assignmentAllocationDao.update(allocation);
            }
            
            // 若任一更新失败，则回滚事务
            if (result1 == 0 || result2 == 0) {
                throw new RuntimeException("批改作业失败：数据库更新异常");
            }
            
            // 获取更新后的提交记录
            Submission updatedSubmission = submissionDao.getById(submissionId);
            return Result.success(updatedSubmission);
        } catch (Exception e) {
            logger.error("批改作业失败，提交ID: " + submissionId, e);
            throw e; // 重新抛出异常，触发事务回滚
        }
    }

    @Override
    public Result<String> downloadSubmissionFiles(Long assignmentId, HttpServletResponse response) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            List<Submission> submissions = submissionDao.findByAssignmentId(assignmentId);
            if (submissions.isEmpty()) {
                return Result.error("没有找到提交记录");
            }
            
            // 设置响应信息
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + 
                    URLEncoder.encode(assignment.getTitle() + "_提交文件.zip", "UTF-8"));
            
            // 创建zip输出流
            ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
            
            // 添加文件到zip
            for (Submission submission : submissions) {
                if (submission.getFileUrl() != null && !submission.getFileUrl().isEmpty()) {
                    try {
                        // 这里应该实现从OSS下载文件并添加到zip的逻辑
                        // 由于涉及到外部资源，这里只是简化处理
                        // addFileToZip(zipOut, submission, studentMap);
                        
                        // 示例实现（实际应该从OSS获取文件流）
                        String studentName = submission.getStudentName() != null ? 
                                submission.getStudentName() : submission.getStudentId();
                        String fileName = studentName + "_" + submission.getStudentId() + "_V" + 
                                submission.getVersion() + getFileExtension(submission.getFileUrl());
                        
                        // 在实际实现中，这里应当从OSS获取文件并添加到zip
                        // 这里仅作为示例，输出一个占位文件
                        zipOut.putNextEntry(new ZipEntry(fileName));
                        String content = "This is a placeholder for file: " + submission.getFileUrl();
                        zipOut.write(content.getBytes());
                        zipOut.closeEntry();
                    } catch (Exception e) {
                        logger.error("添加文件到zip失败: " + submission.getFileUrl(), e);
                    }
                }
            }
            
            zipOut.close();
            return Result.success("下载成功");
        } catch (Exception e) {
            logger.error("批量下载提交文件失败，作业ID: " + assignmentId, e);
            return Result.error("批量下载提交文件失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取文件扩展名
     * 
     * @param fileUrl 文件URL
     * @return 文件扩展名
     */
    private String getFileExtension(String fileUrl) {
        if (fileUrl == null || fileUrl.isEmpty()) {
            return "";
        }
        int lastDotIndex = fileUrl.lastIndexOf('.');
        if (lastDotIndex >= 0) {
            return fileUrl.substring(lastDotIndex);
        }
        return "";
    }

    @Override
    public Result<String> exportSubmissions(Long assignmentId, HttpServletResponse response) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            List<Submission> submissions = submissionDao.findByAssignmentId(assignmentId);
            
            // 创建Excel工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("作业提交记录");
            
            // 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {"学号", "姓名", "提交时间", "状态", "分数", "是否迟交", "版本"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }
            
            // 填充数据
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            int rowNum = 1;
            for (Submission submission : submissions) {
                Row row = sheet.createRow(rowNum++);
                
                row.createCell(0).setCellValue(submission.getStudentId());
                row.createCell(1).setCellValue(submission.getStudentName() != null ? 
                        submission.getStudentName() : "");
                
                if (submission.getSubmitTime() != null) {
                    row.createCell(2).setCellValue(sdf.format(submission.getSubmitTime()));
                } else {
                    row.createCell(2).setCellValue("");
                }
                
                String status = submission.getStatus() == 0 ? "未批改" : "已批改";
                row.createCell(3).setCellValue(status);
                
                if (submission.getScore() != null) {
                    row.createCell(4).setCellValue(submission.getScore());
                } else {
                    row.createCell(4).setCellValue("");
                }
                
                String isLate = submission.getIsLate() == 1 ? "是" : "否";
                row.createCell(5).setCellValue(isLate);
                
                if (submission.getVersion() != null) {
                    row.createCell(6).setCellValue(submission.getVersion());
                } else {
                    row.createCell(6).setCellValue("");
                }
            }
            
            // 调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }
            
            // 设置响应信息
            String fileName = assignment.getTitle() + "_提交记录.xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + 
                    URLEncoder.encode(fileName, "UTF-8"));
            
            // 输出Excel文件
            OutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            workbook.close();
            outputStream.close();
            
            return Result.success("导出成功");
        } catch (Exception e) {
            logger.error("导出作业提交记录失败，作业ID: " + assignmentId, e);
            return Result.error("导出作业提交记录失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Boolean> deleteSubmission(Long submissionId) {
        try {
            Submission submission = submissionDao.getById(submissionId);
            if (submission == null) {
                return Result.error("提交记录不存在");
            }
            
            // 如果有文件，删除OSS上的文件
            if (submission.getFileUrl() != null && !submission.getFileUrl().isEmpty()) {
                ossService.deleteFile(submission.getFileUrl());
            }
            
            // 删除提交记录
            submissionDao.delete(submissionId);
            
            // 查找是否还有其他提交
            Submission latestSubmission = submissionDao.findLatestVersion(
                    submission.getAssignmentId(), submission.getStudentId());
            
            // 更新作业分配记录
            AssignmentAllocation allocation = assignmentAllocationDao.findByAssignmentIdAndStudentId(
                    submission.getAssignmentId(), submission.getStudentId());
            if (allocation != null) {
                if (latestSubmission != null) {
                    // 将分配记录关联到最新的提交
                    allocation.setSubmissionId(latestSubmission.getSubmissionId());
                    allocation.setStatus(latestSubmission.getStatus() == 0 ? 1 : 2); // 根据提交状态更新
                    allocation.setScore(latestSubmission.getScore());
                } else {
                    // 没有提交记录，重置为未提交状态
                    allocation.setSubmissionId(null);
                    allocation.setStatus(0);
                    allocation.setScore(null);
                }
                assignmentAllocationDao.update(allocation);
            }
            
            return Result.success("删除提交记录成功", true);
        } catch (Exception e) {
            logger.error("删除提交记录失败，提交ID: " + submissionId, e);
            return Result.error("删除提交记录失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> getSubmissionStats(Long assignmentId) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            // 获取提交记录
            List<Submission> submissions = submissionDao.findByAssignmentId(assignmentId);
            
            // 统计信息
            int total = submissions.size();
            int graded = 0;
            int ungraded = 0;
            int lateSubmissions = 0;
            double totalScore = 0;
            double avgScore = 0;
            int maxScore = 0;
            int minScore = 100;
            
            // 计算统计信息
            for (Submission submission : submissions) {
                if (submission.getStatus() == 1) { // 已批改
                    graded++;
                    if (submission.getScore() != null) {
                        totalScore += submission.getScore();
                        maxScore = Math.max(maxScore, submission.getScore());
                        minScore = Math.min(minScore, submission.getScore());
                    }
                } else {
                    ungraded++;
                }
                
                if (submission.getIsLate() == 1) {
                    lateSubmissions++;
                }
            }
            
            // 计算平均分
            if (graded > 0) {
                avgScore = totalScore / graded;
            }
            
            // 如果没有提交，最低分设为0
            if (submissions.isEmpty() || graded == 0) {
                minScore = 0;
            }
            
            // 构建结果
            Map<String, Object> stats = new HashMap<>();
            stats.put("total", total);
            stats.put("graded", graded);
            stats.put("ungraded", ungraded);
            stats.put("lateSubmissions", lateSubmissions);
            stats.put("avgScore", avgScore);
            stats.put("maxScore", maxScore);
            stats.put("minScore", minScore);
            
            return Result.success(stats);
        } catch (Exception e) {
            logger.error("获取提交统计信息失败，作业ID: " + assignmentId, e);
            return Result.error("获取提交统计信息失败: " + e.getMessage());
        }
    }
} 